/**
 *  Copyright 2002-2009 the original author or authors.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package foo.bar.forum.web.extension;

import net.sourceforge.stripes.validation.SimpleError;
import net.sourceforge.stripes.validation.TypeConverter;
import net.sourceforge.stripes.validation.ValidationError;
import org.apache.commons.lang.StringUtils;

import java.util.Collection;
import java.util.Locale;

/**
 * An abstract {@link TypeConverter} that recongnized the following kindof request parameter :-
 * <ul>
 *  <li>"null" - returns the target object as null</li>
 *  <li>"" - instantiate the target object (through it's default constructor)</li>
 *  <li><a String> - defers the conversion to it's subclass (subclass normally assume the number is the
 *      pk for some entity</li>
 * </ul>
 *
 *  eg.
 *  http:// .....?user=null
 *  -> user object in the action will be null
 *
 *  http:// .....?user=
 *  -> user object in the action will be a new instance (instantiated through it's default constructor)
 *
 *  http:// .....?user=3
 *  -> subclass to decide how to return an instance of user object (based on the number 3)
 *
 * @author tmjee
 * @version $Date$ $Id$
 */
public abstract class AbstractIdentifiableTypeConverter<T> implements TypeConverter<T> {

    private Locale locale;

    public void setLocale(Locale locale) {
        this.locale = locale;
    }

    public Locale getLocale() {
        return locale;
    }

    /**
     * Try to identify the request input, if its not "" (empty) or "null" but a number
     * we'll let subclass decides how to convert it to the target object.
     *
     * Else if it's "" (empty), well instantiate the target object using it's default constructor
     *
     * Else if it's "null", well make the target object null.
     * 
     * @param input
     * @param targetType
     * @param errors
     * @return
     */
    public T convert(String input, Class<? extends T> targetType, Collection<ValidationError> errors) {
        if (!StringUtils.isEmpty(input)) {
            if ("null".equalsIgnoreCase(input.trim())) {
                return null;    
            }
            else {
                    if (input != null) {
                        T t =  _convert(input, targetType, errors);
                        return t;
                    }
                    else {
                        try {
                            return (T) targetType.newInstance();
                        } catch (Exception e) {
                            throw new RuntimeException(e);
                        }
                    }
            }
        }
        else {
            try {
                return (T) targetType.newInstance();
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    }

    /**
     * Subclass to determine how to return a conversion target object based on the id.
     * 
     * @param id
     * @param targetType
     * @param errors
     * @return
     */
    protected abstract T _convert(String id, Class<? extends T> targetType, Collection<ValidationError> errors);
}
